<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        function fn1() {
            Promise.resolve()
                .then(() => {
                    console.log(1);
                    // return undefined
                })
                .catch(() => {
                    console.log(2);
                    // return undefined
                })
                .then(() => {
                    console.log(3);
                });
        }
        // fn1()// 1 3

        function fn2() {
            Promise.resolve()
                .then(() => {
                    console.log(1);
                    throw new Error("erro1");
                })
                .catch(() => {
                    console.log(2);
                    // return undefined
                })//无毁约动作（throw reject）即履约
                .then(() => {
                    console.log(3);
                });
        }
        // fn2()

        function fn3() {
            Promise.resolve()
                .then(() => {
                    console.log(1);
                    throw new Error("erro1");
                })
                .catch(() => {
                    console.log(2);
                    // return undefined
                })
                .catch(() => {
                    // 注意这里是 catch
                    console.log(3);
                })
                .then(()=>console.log(4))
        }
        // fn3()

        /* 经典题 */
        function fn4() {
            /* 只要是异步函数 返回值必是Promise */
            async function fn() {
                // 同步代码立即执行
                // console.log("1");
                // 对外返回一个将来履约100的Promise对象
                // return 100;//return Promise.resolve(100)

                console.log("1");//2

                // 对外返回一个将来履约100的Promise对象
                // promise中的执行器代码是同步代码
                return new Promise(
                    // 执行器函数中的代码是同步的
                    (resolve, reject) => {
                        console.log("3");//3
                        resolve(100);
                    }
                );
                console.log("3");//永远不会打印
            }

            (async function () {
                console.log("call 1");//1

                // 调用fn 并立刻得到【一个将来会履约100的Promise对象】
                const a = fn(); //1 3

                console.log("call 2");//4

                // 死等Promise履约的结果
                // await 右侧依然是同步代码
                const b = await fn();//1 第5次打印

                console.log("call 3");//6
                console.log(a);//promise对象
                console.log(b);//100
            })();
        }
        // fn4()

        /* 经典题 */
        function fn5() {
            /* 异步函数走到阻塞处才让出执行权 */
            (async function () {
                try {
                    console.log("start");//1

                    // 阻塞等待身后的promise履约100
                    const a = await 100;//履约100
                    console.log("a", a);//100

                    const b = await Promise.resolve(200);
                    console.log("b", b);//200

                    // 毁约的结果在catch里
                    const c = await Promise.reject(300);

                    console.log("c", c);
                    console.log("end");
                }

                catch (err) {
                    console.log("catch err", err);//ce 300
                }
                
                console.log("444");
            })();

            console.log("GAME OVER!");//2
        }
        // fn5()

        /* 微任务-DOM渲染-宏任务 */
        function fn6() {
            console.log(100);

            setTimeout(
                () => {
                    console.log(200);
                }
            );//宏任务 DOM/BOM-API

            Promise.resolve()//立刻同步地得到Promise对象
                .then(
                    () => {
                        console.log(300);
                    }
                );//微任务 promise.then/catch

            console.log(400);
        }
        // fn6()

        /* 经典题 今日头条promise面试题 */
        function fn7() {
            async function async1() {
                console.log('async1 start')//2

                // 开始死等履约结果（后续皆为异步回调）
                // await会阻塞后续代码
                await 0 //履约0
                async2()
                console.log('async1 end')//6
            }
            async function async2() {
                console.log('async2')//5
            }  
            console.log('script start')//1
            setTimeout(function () {
                console.log('setTimeout')//8
            }, 0)
            async1()
            new Promise(
                // 立刻执行
                function (resolve) {
                    console.log('promise1')//3
                    // resolve/reject之前均为同步
                    resolve()
                }
            )
                // 从这里开始才是异步
                .then(
                    function () {
                        console.log('promise2')//7
                    }
                )
            console.log('script end')//4
        }
        fn7()

    </script>
</body>

</html>